perm filename VISIO.PAL[AL,HE]3 blob sn#590384 filedate 1981-05-29 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	Routines to communicate with the Vision Module via the DR11-C
C00008 00003	Interrupt routines
C00010 00004	Sending routines
C00014 00005	Receiving routines
C00017 00006	Reset & bad requests
C00018 00007	Data & Constants
C00021 ENDMK
C⊗;
;Routines to communicate with the Vision Module via the DR11-C

; COMMANDS are:
	VMTRANS= 040000		; TRANSFER DATA COMMAND
	ERESET=	140000		; RESET
	ERESAK=	160000		; RESET ACKNOWLEDGE

; STATUS word values are:
;	OK=	0		; DONE WITH A CLR
	ERBUF0=	101000		; NO BUFFERS AVAILABLE FOR INPUT MESSAGE
	ERBUFS=	102000		; NEXT BUFFER IS TOO SMALL
	ERCHKS=	103000		; CHECKSUM ERROR

;DR11-C definitions

DRCSR  = 763750		;Control and Status register
DROBUF = 763752		;Output Buffer register
DRIBUF = 763754		;Input Buffer register

DRIVEC = 360 		;Request A & B interrupt vectors

;	.=DRIVEC
;	DRINTA			;Req A interrupt handler
;	200			;Level 4
;	DRINTB			;Req B interrupt handler
;	200			;Level 4

;Routine to send a message over to the Vision Module & await a reply.
;No arguments since we use fixed buffers & the message is already set up.
;Clobbers R0 & R1

CODE
VMSEND:	TST VMINIT		;Have we initialized the DR11-C link?
	BNE 3$			; yes - skip ahead
	INC VMINIT		; no - only initialize once
	MOV #50040,VMPDB+UPSW	;So we use supervisor mode
	FORK #VMPDB,#VMNULL,#USRDM ;Start up VM null job - so we'll have a good sp
	SLEEP #200.		;Now wait for it to be set up (probably don't need this)
	MOV #2,DRCSR		;Send VM a Req B, should clean things up some
	SETVEC	#DRIVEC,#DRINTA,#50240	;Set up interrupt vectors
	SETVEC	#DRIVEC+4,#DRINTB,#50240 ;Use Supervisor mode, priority level 5

;Check that Vision Module is powered up

	TST DRCSR		;See if Req B currently set
	BNE 2$			; Yes - VM must be on
1$:	SETPRI #5		;Set our priority up to 5 so we aren't interrupted
	MOV #40,DRCSR		;Turn on Int B
	MOV DRCSR,R0		;Remember CSR
	CLR DRCSR		;Turn off interrupts
	SETPRI			;Restore our old priority
	TST R0			;Did Req B go on when we enabled interrupts?
	BPL 2$			; No - everything's okay
	ALERR VMNPWR		; Yes - Complain
	BR 1$			;Let user try to fix things

;See if anyone's home

2$:	MOV #6,VMSTATE		;Send a RESET & see if it gets acknowledged
	MOV #ERESET,DROBUF
	MOV #141,DRCSR		;Enable interrupts & Int A in VM

	SLEEP #500.		;Now wait 500 msecs for the reset acknowledge
	TST VMSTATE
	BEQ 3$			;VMSTATE will be set to 0 if we get the resak
	ALERR VMTMES		;Time out - complain
	BR 2$			;Try again

3$:	BIS #2,DRCSR		;Set CSR 1 for "B" response (may not be needed)
	MOV VMSBUF,R1		;R1 ← Message length in bytes
	MOV R1,R0
	INC R0			;In case odd number of bytes
	ASR R0			;Convert bytes → word count
	MOV R0,VMSCNT		;Set up word count
	MOV #VMSBUF+2,VMSPTR	;Set up pointer at message
	MOV #VMRBUF,VMRPTR	;Reset receive message pointer
	BIS #VMTRANS,R1		;R1 ← Send command bits + byte count
	MOV R1,DROBUF		;Get ready to send it
	BIC #3,DRCSR		;Clear CSR 0 & 1 bits
	MOV #1,VMSTATE
	CLR VMSDONE
	CLR VMRDONE
	INC DRCSR		;"A" Request for command

	MOV #20.,R0
4$:	TST VMSDONE		;Wait for it to have been sent
	BNE 5$
	SLEEP #50.		;Sleep for 50 msecs
	SOB R0,4$		;Try it again
	ALERR VMTMES		;Time out after 1 second - complain
	BR VMSEND		;Try again from the top

5$:	MOV #200.,R0
6$:	TST VMRDONE		;Wait for reply to have been received
	BNE 7$
	SLEEP #50.		;Sleep for 50 msecs
	SOB R0,6$		;Try it again
	ALERR VMTMES		;Time out after 10 seconds - complain
	JMP VMSEND		;Try again from the top

7$:	RTS PC

;Interrupt routines

DRINTA:	MOV R0,-(SP)
	MOV #ADISP,R0		;Use A dispatch table
	BR DRINT
DRINTB:	MOV R0,-(SP)
	MOV #BDISP,R0		;Use B dispatch table
DRINT:	MOV R1,-(SP)
	BIC #3,DRCSR		;Clear interrupt requests
	MOV DRIBUF,R1		;R1 ← Anything sent over to us
	ADD VMSTATE,R0
	ADD VMSTATE,R0		;Get offset into dispatch table
	JMP @0(R0)			;Go do it

VMINTB:	BIS #2,DRCSR		;Signal with a B request
VMINTR:	MOV (SP)+,R1
	MOV (SP)+,R0
	KRTI			;Have kernel do the RTI for us

VMNULL:	MOV USKMAX+VMPDB,SP	;Make sure we have a good stack pointer
	DISMIS			;Now go away

;Sending routines

; In case he's not ready to start receiving when we want to send

VMA1:	BIC #777,R1		;Clear all non-status bits
	CLR VMSTATE		;So we can receive
	INC VMERRS		;Update error count
	CMP #ERBUF0,R1		;No buffers error?
	BNE 1$
	ALERR NBFMES		;Complain
	BR 4$			; & try again
1$:	CMP #ERBUFS,R1		;Buffer too small?
	BNE 2$
	ALERR SBFMES		;Complain
	BR 4$			; & try again
2$:	CMP #ERESET,R1		;External Reset?
	BEQ 3$
	ALERR ERRMES		;Who know's what's going on?
	BR 4$			; Try again
3$:	MOV #ERESAK,DROBUF	;Send a reset acknowledge
	INC DRCSR		;Int A
4$:	INC VMRESN		;Update count of resent messages
	BIC #3,DRCSR		;Clear interrupts
	BIS #2,DRCSR		;Set CSR 1 for "B" response (may not be needed)
	MOV VMSBUF,R1		;R1 ← Message length in bytes
	MOV R1,R0
	INC R0			;In case odd number of bytes
	ASR R0			;Convert bytes → word count
	MOV R0,VMSCNT		;Set up word count
	MOV #VMSBUF+2,VMSPTR	;Set up pointer at message
	BIS #VMTRANS,R1		;R1 ← Send command bits + byte count
	MOV R1,DROBUF		;Get ready to send it
	MOV #1,VMSTATE
	INC DRCSR		;"A" Request for command
	BR VMINTR		;Maybe it'll work

;It's okay with him to send - ship it over

VMB1:	INC VMSTATE
	CLR VMCKSUM		;Get ready to send message over
VMB2:	DEC VMSCNT		;More to send?
	BPL 1$			; yes - do it
	MOV VMCKSUM,DROBUF	; no - go send cksum
	INC VMSTATE		; Update VMSTATE
	BR VMINTB		; B Req & return
1$:	MOV @VMSPTR,R0		;Fetch next word to send
	XOR R0,VMCKSUM		;Update check sum
	MOV R0,DROBUF		;Move it to output buffer
	ADD #2,VMSPTR		;Bump pointer
	BR VMINTB		;B Req & return

;Done sending - see if he received it okay

VMA3:	TST R1			;Check status
	BMI 1$			; Error skip ahead
	CLR VMSTATE		;Done here
	INC VMSDONE
	BR VMINTB		;B Req & return so VM can continue

1$:	INC VMERRS		;Update error count
	CMP #ERESET,R1		;Remote Reset?
	BNE 2$			; no
	MOV #ERESAK,DROBUF	;Send a reset acknowledge
	INC DRCSR		;Int A
2$:	INC VMRESN		;Update count of resent messages
	BIC #3,DRCSR		;Clear interrupts
	BIS #2,DRCSR		;Set CSR 1 for "B" response (may not be needed)
	MOV VMSBUF,R1		;R1 ← Message length in bytes
	MOV R1,R0
	INC R0			;In case odd number of bytes
	ASR R0			;Convert bytes → word count
	MOV R0,VMSCNT		;Set up word count
	MOV #VMSBUF+2,VMSPTR	;Set up pointer at message
	BIS #VMTRANS,R1		;R1 ← Send command bits + byte count
	MOV R1,DROBUF		;Get ready to send it
	MOV #1,VMSTATE
	INC DRCSR		;"A" Request for command
	JMP VMINTR		;Return from interrupt

;Receiving routines

;Ready to start receiving

VMA0:	TST R1			;See if transfer request
	BGT 3$			; yes - skip ahead & do it
	BIC #17777,R1		;Clear all except command bits
	BNE 1$
	JMP VMINTB		;Null status - just ignore
1$:	CMP #ERESET,R1		;Make sure it was a reset
	BNE 2$
	MOV #ERESAK,DROBUF	;Send a reset acknowledge
	INC DRCSR		;Int A & return
	JMP VMINTR
2$:	ALERR ERRMES		;What's going on?
	INC VMERRS		;Update error count
	MOV #ERESET,DROBUF	;Try to reset things
	INC DRCSR
	MOV #6,VMSTATE		;Wait for reset acknowledgement
	JMP VMINTR

3$:	BIC #VMTRANS,R1		;Clear command bits
	MOV R1,@VMRPTR		;Store byte count
	ADD #2,VMRPTR
	INC R1			;In case odd number of bytes
	ASR R1			;Convert bytes to words
	MOV R1,VMRCNT		;Store it
	CLR VMCKSUM
	MOV #4,VMSTATE		;Receive data
	JMP VMINTB		;B response & return

;Store the message away now

VMB4:	DEC VMRCNT		;More to message?
	BMI 1$			; no - go get checksum
	MOV R1,@VMRPTR		;Store data away
	ADD #2,VMRPTR
	XOR R1,VMCKSUM		;Accumulate checksum
	JMP VMINTB		;B response & return

1$:	CMP R1,VMCKSUM		;Checksum okay
	BNE 2$			; No
	INC VMSTATE		; Yes - send ok status & wait til ok to proceed
	CLR DROBUF
	INC DRCSR		;A response & return
	JMP VMINTR

2$:	INC VMERRS		;Update error count
	INC VMRERV		;Update count of requested retransmissions
	CLR VMSTATE
	MOV #ERCHKS,DROBUF
	INC DRCSR		;Req A
	JMP VMINTR

;Done receiving

VMB5:	INC VMRDONE		;Let everyone know that we're done
	CLR VMSTATE
	JMP VMINTR

;Reset & bad requests


;Waiting for Reset Acknowledgement

VMA6:	BIC #17777,R1		;Strip to command bits
	CMP #ERESET,R1		;Check for VM reseting also
	BNE 2$			; no
	MOV #ERESAK,DROBUF	; yes - acknowledge his
	INC DRCSR		;Req A & return
1$:	JMP VMINTR
2$:	CMP #ERESAK,R1		;Is VM acknowledging us?
	BNE 1$			; no - ignore it
	CLR VMSTATE		; yes - ok
	JMP VMINTB		;B response & return

;Ignore Req B's

VMB0:	JMP VMINTR

;Bad Requests

VMABAD: ;ALERR ABDMES		;Don't Complain
	INC VMERRS		;Update error count
	JMP VMINTR

VMBBAD:	;ALERR BBDMES		;Don't Complain
	INC VMERRS		;Update error count
	JMP VMINTR

;Data & Constants

DATA
VMPDB:: PDBLK 2,40	;So we'll have a good stack pointer for interrupts

VMINIT:: 0		;Have we inited yet
VMSTATE:: 0		;What we're doing:
			;  0 = nothing
			;  1 = waiting for ok to start sending
			;  2 = sending data & cksum
			;  3 = waiting for message received ok
			;  4 = receiving data & cksum
			;  5 = waiting for ok to continue
			;  6 = reset in progress

ADISP:: .WORD VMA0,VMA1,VMABAD,VMA3,VMABAD,VMABAD,VMA6	;Req A dispatch table
BDISP:: .WORD VMB0,VMB1,VMB2,VMBBAD,VMB4,VMB5,VMBBAD	;Req B dispatch table

VMSBUF:: .BLKW 100	;Message to send
VMRBUF:: .BLKW 100	;Where we store the reply to our message

VMSPTR:: VMSBUF		;What to send next
VMSCNT:: 0		;How much left to send
VMRPTR:: VMRBUF		;Where to store next word
VMRCNT:: 0		;How much left to receive
VMCKSUM:: 0

VMSDONE:: .WORD 0		;Set when message has been sent
VMRDONE:: .WORD 0		;Set when reply has been received

;Random statistics we'll never look at

VMERRS:: 0	;# of errors
VMRESN:: 0	;# of resent messages
VMRERV:: 0	;# of resent replies

;Error messages

VMTMES:: .ASCIZ /πTime out - Make sure Vision Module is ready./
VMNPWR:: .ASCIZ /πVision Module not turned on. Power it up & continue./
RESMES:: .ASCIZ /πExternal reset./
NBFMES:: .ASCIZ /πNo available buffers in VM./
SBFMES:: .ASCIZ /πToo small buffer in VM./
ERRMES:: .ASCIZ /πUnknown error./
ABDMES:: .ASCIZ /πUnexpected A Request./
BBDMES:: .ASCIZ /πUnexpected A Request./
.EVEN

CODE